﻿namespace Knownet.BNF.Inline
{
  using System;
  using System.Text;
  using System.Collections;
  using Knownet.AST;

  /// <summary>
  /// BNF的基本定义项。
  /// 例如终结符，非终结符
  /// 以及引用。
  /// </summary>
  public class BnfPrimitive : SyntaxNode
  {
    #region Consts
    /// <summary>
    /// 重复符号，用于生成简单内联语法。
    /// </summary>
    public const string RepeatableSign = "++";
    /// <summary>
    /// 可选符号，用于生成简单内联语法。
    /// </summary>
    public const string OptionalSign = "~";
    /// <summary>
    /// 终结符符号，用于生成简单内联语法。
    /// </summary>
    public const string TerminalSign = "T";
    /// <summary>
    /// 非终结符符号，用于生成简单内联语法。
    /// </summary>
    public const string NontermialSign = "N";
    /// <summary>
    /// 引用符号，用于生成简单内联语法。
    /// </summary>
    public const string ReferenceSign = "R";
    #endregion
    #region Statics
    #region Shortcuts
    /// <summary>
    /// 创建新的BnfPrimitive实例。
    /// </summary>
    /// <returns></returns>
    public static new BnfPrimitive CreateInstance()
    {
      return new BnfPrimitive();
    }
    /// <summary>
    /// 创建签名为signature的实例。
    /// </summary>
    public static BnfPrimitive of(string signature)
    {
      return new BnfPrimitive(signature);
    }
    #endregion
    #region Operators
    /// <summary>
    /// BnfPrimitive到BnfDefinition的转换。
    /// </summary>
    public static implicit operator BnfDefinition(BnfPrimitive item)
    {
      return item != null ? BnfDefinition.accordingTo(item.Signature, (BnfClause)item) : null;
    }
    /// <summary>
    /// BnfPrimitive到BnfClause的转换。
    /// </summary>
    public static implicit operator BnfClause(BnfPrimitive item)
    {
      return BnfClause.succeeding(item);
    }
    /// <summary>
    /// BnfClause 选择符重载，相当于BNF子句之间的"|"。
    /// </summary>
    /// <returns>选择生成定义。</returns>
    public static BnfDefinition operator +(BnfPrimitive left, BnfPrimitive right)
    {
      return BnfClause.succeeding(left) + BnfClause.succeeding(right);
    }
    /// <summary>
    /// BnfPrimitive 连接符重载，相当于BNF子句中
    /// 各个项之间的空白。
    /// </summary>
    /// <returns>连接生成子句。</returns>
    public static BnfClause operator *(BnfClause clause, BnfPrimitive item)
    {
      if (clause != null)
      {
        return clause.Join(item);
      }
      return clause;
    }
    /// <summary>
    /// BnfPrimitive可重复设置。
    /// </summary>
    /// <remarks>
    /// 此操作符使BnfPrimitive成为可重复的，
    /// 即设定它的IsRepeatable为true。
    /// </remarks>
    public static BnfPrimitive operator ++(BnfPrimitive item)
    {
      if (item != null)
      {
        item.IsRepeatable = true;
      }
      return item;
    }
    /// <summary>
    /// BnfPrimitive可选择设置。
    /// </summary>
    /// <remarks>
    /// 此操作符使BnfPrimitive成为可选择的，
    /// 即设定它的IsOptional为true。
    /// </remarks>
    public static BnfPrimitive operator ~(BnfPrimitive item)
    {
      if (item != null)
      {
        item.IsOptional = true;
      }
      return item;
    }
    /// <summary>
    /// 将语义动作和当前子句（由单一BnfPrimitive构成）
    /// 相关联。
    /// </summary>
    public static BnfClause operator /(BnfPrimitive item, SemanticAction actiontMethod)
    {
      return BnfClause.succeeding(item) / actiontMethod;
    }
    #endregion
    #endregion
    #region Fields
    #endregion
    #region Properties
    /// <summary>
    /// 判断或者设定当前节点是否为可选节点。
    /// </summary>
    public virtual bool IsOptional
    {
      get
      {
        return this.HasContainingAttributeOf(BnfAttribute.Optional);
      }
      set
      {
        this.SetContainingAttributeOf(BnfAttribute.Optional, value);
      }
    }
    /// <summary>
    /// 判断或者设定当前节点是否为可重复节点。
    /// </summary>
    public virtual bool IsRepeatable
    {
      get
      {
        return this.HasContainingAttributeOf(BnfAttribute.Repeatable);
      }
      set
      {
        this.SetContainingAttributeOf(BnfAttribute.Repeatable, value);
      }
    }
    /// <summary>
    /// 判断或者设定当前节点是否是文本节点。
    /// </summary>
    public virtual bool IsLiteral
    {
      get
      {
        return this.HasContainingAttributeOf(BnfAttribute.Literal);
      }
      set
      {
        this.SetContainingAttributeOf(BnfAttribute.Literal, value);
      }
    }
    /// <summary>
    /// 判断或者设定当前节点是否为引用节点。
    /// </summary>
    public virtual bool IsReference
    {
      get
      {
        return this.HasContainingAttributeOf(BnfAttribute.Reference);
      }
      set
      {
        this.SetContainingAttributeOf(BnfAttribute.Reference, value);
      }
    }

    #endregion
    #region Constructors
    public BnfPrimitive() : this(String.Empty) { }
    public BnfPrimitive(string signature) : base(signature) { }
    #endregion
    #region Methods
    /// <summary>
    /// 判别当前基本定义项是否具有指定的属性。
    /// </summary>
    /// <param name="attribute">指定的属性。</param>
    /// <returns>如果具有指定属性，返回true；否则返回false。</returns>
    public virtual bool HasContainingAttributeOf(BnfAttribute attribute)
    {
      if (attribute != null && this.HasContainingNodes)
      {
        foreach(BnfAttribute att in this.ContainingNodes)
        {
          if (att.IsAliasOf(attribute))
            return true;
        }
      }
      return false;
    }
    /// <summary>
    /// 设定当前基本定义项，使其具有或者不具有某种指定属性。
    /// </summary>
    /// <param name="hasAttribute">指定是否具有这种属性。</param>
    /// <param name="attribute">指定的属性。</param>
    /// <returns>如果具有指定属性，返回true；否则返回false。</returns>
    public virtual bool SetContainingAttributeOf(BnfAttribute attribute, bool hasAttribute)
    {
      return hasAttribute ? this.SetContainingAttributeOf(attribute) :
        this.ClearContainingAttributeOf(attribute);
    }
    
    /// <summary>
    /// 设定当前基本定义项，使其具有指定属性。
    /// </summary>
    /// <param name="attribute">指定的属性。</param>
    /// <returns>如果具有指定属性，返回true；否则返回false。</returns>
    protected virtual bool SetContainingAttributeOf(BnfAttribute attribute)
    {
      if (!this.HasContainingAttributeOf(attribute))
      {
        this.AddContainingNodes(attribute);
        return false;
      }
      return true;
    }
    /// <summary>
    /// 清除当前基本定义项，使其不具有指定属性。
    /// </summary>
    /// <param name="attribute">指定的属性。</param>
    /// <returns>如果具有指定属性，返回true；否则返回false。</returns>
    protected virtual bool ClearContainingAttributeOf(BnfAttribute attribute)
    {
      if (this.HasContainingAttributeOf(attribute))
      {
        this.RemoveContainingNodes(attribute);
        return true;
      }
      return false;
    }
    /// <summary>
    /// 重载的方法显示BNF定义的简单内联语法。
    /// </summary>
    /// <remarks>
    /// 关于简单内联语法，请参阅BnfDefinition
    /// 的说明。
    /// </remarks>
    public override string ToString()
    {
      StringBuilder builder = new StringBuilder();
      if (this.IsOptional)
      {
        builder.Append(OptionalSign);
      }
      if (this.IsLiteral)
      {
        builder.AppendFormat("{0}(\"{1}\")", TerminalSign, this.Signature);
      }
      else if (this.IsReference)
      {
        builder.AppendFormat("{0}(\"{1}\")", ReferenceSign, this.Signature);
      }
      else
      {
        builder.AppendFormat("{0}(\"{1}\")", NontermialSign, this.Signature);
      }

      if (this.IsRepeatable)
      {
        builder.Append(RepeatableSign);
      }

      return builder.ToString();
    }
    #endregion
  }
}
